package com.demarc.pesquisas.infraestrutura.util.utils;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;

import javax.faces.context.FacesContext;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;

import com.demarc.pesquisas.negocio.entidade.DiaSemanaEnum;

public class DataUtils {

	public static final Locale LOCALE_PT_BR = new Locale("pt", "br");
	public static final String DATA_PADRAO_PT_BR_COM_TRACO = "dd-MM-yyyy";
	public static final String DATA_PADRAO_PT_BR = "dd/MM/yyyy";
	public static final String DATA_PADRAO_EN_US = "MM/dd/yyyy";
	public static final String PADRAO_ANO = "yyyy";
	public static final String ANO = " ano";
	public static final String ANOS = " anos";
	public static final String MES = " mês ";
	public static final String MESES = " meses";
	public static final String E = " e ";
	public static final String HORA_PADRAO_HH_MM = "HH:mm";
	public static final String HORA_PADRAO_HH_MM_SS = "HH:mm:ss";
	public static final String BARRA = "/";
	public static final String TRACO = "-";
	public static final String COMPLEMENTO_AS = " ás ";

	public static LocalDate converterStringParaLocalDate(String valor,
			String padraoData) {
		LocalDate data = null;
		if (StringUtils.isNotBlank(valor)) {
			DateTimeFormatter formatador = getFormatadorData(padraoData);
			data = formatador.parseDateTime(valor.trim()).toLocalDate();
		}
		return data;
	}

	public static String getPadraoData(Locale locale) {
		String pattern = DATA_PADRAO_EN_US;

		if (LOCALE_PT_BR.getLanguage().equalsIgnoreCase(locale.getLanguage())) {
			pattern = DATA_PADRAO_PT_BR;
		}

		return pattern;
	}

	public static String getPadraoData() {
		Locale locale = LOCALE_PT_BR;

		FacesContext context = FacesContext.getCurrentInstance();
		if (context != null) {
			locale = context.getViewRoot().getLocale();
		}

		return getPadraoData(locale);
	}

	public static String converterLocalDateParaString(LocalDate valor,
			String padraoData) {
		String dataString = null;
		if (valor != null) {
			DateTimeFormatter formatador = getFormatadorData(padraoData);
			dataString = valor.toString(formatador);
		}
		return dataString;
	}

	public static String converterDateTimeParaString(DateTime valor,
			String padraoData) {
		String dataString = null;
		if (valor != null) {
			DateTimeFormatter formatador = getFormatadorData(padraoData);
			dataString = valor.toString(formatador);
		}
		return dataString;
	}

	public static String converterDateParaString(Date data, String padraoData) {
		String dataString = null;
		if (data != null) {
			SimpleDateFormat formatador = new SimpleDateFormat(padraoData);
			dataString = formatador.format(data);
		}
		return dataString;
	}

	private static DateTimeFormatter getFormatadorData(String padraoData) {
		return new DateTimeFormatterBuilder().appendPattern(padraoData)
				.toFormatter().withLocale(LOCALE_PT_BR);
	}

	public static boolean isDataComPadraoDDMMAAA(String data) {
		Pattern padrao = Pattern.compile("^\\d{2}/\\d{2}/\\d{4}$");
		return padrao.matcher(data).matches();
	}

	/**
	 * Avaliar se a data é um sábado ou domingo.
	 * 
	 * @param data
	 *            Data a ser avaliada.
	 * 
	 * @return true se o dia for um sábado ou domingo, false para os outros dias
	 *         da semana.
	 */
	public static boolean isFimDeSemana(LocalDate data) {
		List<Integer> finaisSemana = Arrays.asList(DateTimeConstants.SATURDAY,
				DateTimeConstants.SUNDAY);

		return finaisSemana.contains(data.getDayOfWeek());
	}

	public static boolean isDiaSemanaValido(LocalDate data,
			List<DiaSemanaEnum> listaDiasSemanaDisciplinaDiario) {

		boolean isDiaSemanaValido = false;
		for (DiaSemanaEnum diaSemanaEnum : listaDiasSemanaDisciplinaDiario) {
			if (DiaSemanaEnum.obterDiaPor(data.dayOfWeek().get()).getCodigo()
					.equalsIgnoreCase(diaSemanaEnum.getCodigo())) {

				isDiaSemanaValido = true;
				break;
			}
		}
		return isDiaSemanaValido;
	}

	/**
	 * Obtém o último dia de um mes a partir de uma data.
	 * 
	 * @param dataMes
	 *            - Data que a partir dela será verificada a última data do mês.
	 */
	public static LocalDate obterUltimoDiaMes(LocalDate dataMes) {
		return dataMes.dayOfMonth().withMaximumValue();
	}

	/**
	 * Retorna o ano atual.
	 * 
	 * @return o ano atual.
	 */
	public static String obterAnoAtual() {
		return obterDataAtual().toString(PADRAO_ANO);
	}

	public static String replaceTracoPorBarra(DateTime date) {
		return date == null ? StringUtils.EMPTY : date.toString(
				DATA_PADRAO_PT_BR_COM_TRACO).replace(TRACO, BARRA);
	}

	public static String replaceTracoPorBarra(LocalDate date) {
		return date == null ? StringUtils.EMPTY : date.toString(
				DATA_PADRAO_PT_BR_COM_TRACO).replace(TRACO, BARRA);
	}

	public static String obterHora(DateTime date) {
		return date == null ? StringUtils.EMPTY : date
				.toString(HORA_PADRAO_HH_MM);
	}

	/**
	 * Retorna o ano atual.
	 * 
	 * @return o ano atual.
	 */
	public static LocalDate obterDataAtual() {
		return obterDataHoraAtual().toLocalDate();
	}

	public static DateTime obterDataHoraAtual() {
		return DateTime.now();
	}
}
